home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-08-16 | 17.9 KB | 671 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: EditViews.h
- // Release Version: $ ODF 1 $
- //
- // Author: Mary Boetcher
- //
- // Copyright: (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include "IntlTest.hpp"
-
- #ifndef EDITVIEWS_H
- #include "EditViews.h"
- #endif
-
- #ifndef DEFINES_K
- #include "Defines.k"
- #endif
-
- #ifndef COMMANDS_H
- #include "Commands.h"
- #endif
-
- // ----- Part Layer -----
-
- #ifndef FWEDVIEW_H
- #include "FWEdView.h"
- #endif
-
- #ifndef FWEVENT_H
- #include "FWEvent.h"
- #endif
-
- #ifndef FWCONTXT_H
- #include "FWContxt.h"
- #endif
-
- #ifndef FWFRAME_H
- #include "FWFrame.h"
- #endif
-
- // ----- Foundation Layer -----
-
- #ifndef FWINTERE_H
- #include "FWIntere.h"
- #endif
-
- // ----- Macintosh Includes -----
-
- #ifndef __SCRIPT__
- #include <Script.h>
- #endif
-
- #ifndef __GESTALT__
- #include <Gestalt.h>
- #endif
-
- #ifndef __AEPACKOBJECT__
- #include <AEPackObject.h>
- #endif
-
- //========================================================================================
- // RunTime Info
- //========================================================================================
-
- #ifdef FW_BUILD_MAC
- #pragma segment odfIntlTest
- #endif
-
- //========================================================================================
- // Constants and Globals
-
- FW_CFont gFontOsaka(FW_CString32("Osaka"), FW_kPlain, FW_IntToFixed(14));
-
- #define cTypingCommand 110
- #define cTSMTypingCommand 111
-
- //----------------------------------------------------------------------------------------
- // Pre- and post-update callback procs for TSMTE
-
- pascal void MyTSMTEPreUpdateProc(TEHandle textH, long refCon);
-
- pascal void MyTSMTEPostUpdateProc(TEHandle textH,
- long fixLen, long inputAreaStart, long inputAreaEnd,
- long pinStart, long pinEnd, long refCon);
-
- static TSMTEPreUpdateUPP gTSMTEPreUpdateUPP = NULL;
- static TSMTEPostUpdateUPP gTSMTEPostUpdateUPP = NULL;
-
- //========================================================================================
- // TSMTE callback routines
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- pascal void MyTSMTEPreUpdateProc(TEHandle textH, long refCon)
- {
- FW_TRY
- {
- CJapEditView* editView = (CJapEditView*)refCon; /* !!! */
-
- if (editView->IsFirstEventInSequence())
- {
- //--- Make a new typing command and save the Undo state
- editView->DoMakeTypingCommand();
- }
- }
- FW_CATCH_BEGIN
- FW_CATCH_EVERYTHING()
- {
- // do nothing; no way to return an error
- }
- FW_CATCH_END
- }
-
- //----------------------------------------------------------------------------------------
- pascal void MyTSMTEPostUpdateProc(TEHandle textH,
- long fixLen, long inputAreaStart, long inputAreaEnd,
- long pinStart, long pinEnd, long refCon)
- {
- // fixLen is the length of the confirmed text in bytes.
- FW_UNUSED(inputAreaStart);
- FW_UNUSED(inputAreaEnd);
- FW_UNUSED(pinStart);
- FW_UNUSED(pinEnd);
- FW_TRY
- {
- if (fixLen > 0) // some characters were confirmed
- {
- CJapEditView* editView = (CJapEditView*)refCon; /* !!! */
- Environment* ev = somGetGlobalEnvironment();
-
- //--- Add the confirmed characters to the typing command
- char* p = (char*) (*((**textH).hText)) + pinEnd - fixLen;
- CTSMInput input(p, fixLen);
- editView->AddInput(ev, &input);
-
- //--- Tell the edit view to notify the document that it's been changed
- editView->Notify(ev, CEditNotification(editView));
- }
- }
- FW_CATCH_BEGIN
- FW_CATCH_EVERYTHING()
- {
- // do nothing; no way to return an error
- }
- FW_CATCH_END
- }
-
- //========================================================================================
- // FW_MTSMHandler
- //========================================================================================
-
- FW_DEFINE_CLASS_M0(FW_MTSMHandler)
-
- //----------------------------------------------------------------------------------------
- FW_MTSMHandler::FW_MTSMHandler(FW_CEditView* theView)
- {
- fEditView = theView;
- fTSMDocId = NULL;
- fTSMHandle = NULL;
- fError = noErr;
- }
-
- //----------------------------------------------------------------------------------------
- FW_MTSMHandler::~FW_MTSMHandler()
- {
- if (fTSMDocId)
- fError = ::DeleteTSMDocument(fTSMDocId);
- fTSMHandle = NULL;
- fEditView = NULL;
-
- // Dispose any UPPs we made
- if (gTSMTEPreUpdateUPP)
- {
- DisposeRoutineDescriptor(gTSMTEPreUpdateUPP);
- gTSMTEPreUpdateUPP = NULL;
- }
- if (gTSMTEPostUpdateUPP)
- {
- DisposeRoutineDescriptor(gTSMTEPostUpdateUPP);
- gTSMTEPostUpdateUPP = NULL;
- }
- }
-
- //----------------------------------------------------------------------------------------
- FW_Boolean FW_MTSMHandler::CreateTSMDocument(TEHandle te)
- {
- FW_Boolean result = false;
-
- // Check for the presence of TSMTE
- long gestaltResponse;
- ODBoolean hasTSMTE;
- if (Gestalt(gestaltTSMTEAttr, &gestaltResponse) == noErr)
- hasTSMTE = (gestaltResponse & (1<<gestaltTSMTEPresent) != 0);
-
- if (hasTSMTE) // Don't create a TSM document if TSMTE is not present
- {
- TSMDocumentID id = NULL;
- InterfaceTypeList supportedTypes;
- supportedTypes[0] = kTSMTEInterfaceType;
- TSMTERecHandle tsmHandle;
-
- fError = ::NewTSMDocument(1, supportedTypes, &id, (long) &tsmHandle);
- if (fError == noErr)
- {
- // Create UPPs for pre- and post-update callbacks
- gTSMTEPreUpdateUPP = NewTSMTEPreUpdateProc(&MyTSMTEPreUpdateProc);
- gTSMTEPostUpdateUPP = NewTSMTEPostUpdateProc(&MyTSMTEPostUpdateProc);
-
- // Initialize the TSM record
- fTSMDocId = id;
- fTSMHandle = tsmHandle;
- (*tsmHandle)->textH = te;
- (*tsmHandle)->preUpdateProc = gTSMTEPreUpdateUPP;
- (*tsmHandle)->postUpdateProc = gTSMTEPostUpdateUPP;
- (*tsmHandle)->updateFlag = kTSMTEAutoScroll;
- (*tsmHandle)->refCon = (long)fEditView; /* !!! */
- result = true;
- }
- }
-
- // Copied from Sample TSMTE DragText
- ::UseInputWindow( kODNULL, false);
-
- return result;
- }
-
- //----------------------------------------------------------------------------------------
- FW_Boolean FW_MTSMHandler::DoActivateTSM(FW_Boolean becomingActive)
- {
- FW_Boolean result = false;
-
- if (fTSMDocId)
- {
- if (becomingActive)
- {
- fError = ::ActivateTSMDocument(fTSMDocId);
-
- // Copied from Sample TSMTE DragText
- ::UseInputWindow( kODNULL, false);
- }
- else
- fError = ::DeactivateTSMDocument(fTSMDocId);
- if (fError == noErr)
- result = true;
- }
-
- return result;
- }
-
- //----------------------------------------------------------------------------------------
- FW_Boolean FW_MTSMHandler::DoFixTSMDocument()
- {
- FW_Boolean result = false;
-
- if (fTSMDocId)
- {
- fError = ::FixTSMDocument(fTSMDocId);
- if (fError == noErr)
- result = true;
- }
-
- return result;
- }
-
- //========================================================================================
- // CJapEditView - for editing Japanese script
- //========================================================================================
-
- FW_DEFINE_AUTO(CJapEditView)
-
- FW_DEFINE_CLASS_M2(CJapEditView, CMyEditView, FW_MTSMHandler);
-
- //----------------------------------------------------------------------------------------
- CJapEditView::CJapEditView(Environment* ev,
- FW_CSuperView* container,
- ODID viewId,
- const FW_CRect& bounds,
- const FW_CFont& font,
- short maxChars,
- unsigned short attributes)
- : CMyEditView(ev, container, viewId, bounds, font, maxChars, attributes),
- FW_MTSMHandler(this),
- fTSMTypingCommand(NULL),
- fMyFont(0),
- fMyFontScript(smJapanese),
- fPreviousFontScript(0),
- fFirstActivation(true)
- {
- }
-
- //----------------------------------------------------------------------------------------
- CJapEditView::~CJapEditView()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // CJapEditView::ActivateTarget
- //----------------------------------------------------------------------------------------
- void CJapEditView::ActivateTarget(Environment* ev, FW_Boolean tabSelection)
- {
- // Save the user's keyboard script
- fPreviousFontScript = ::GetScriptManagerVariable(smKeyScript);
-
- if (fFirstActivation)
- {
- ::KeyScript(fMyFontScript);
- fFirstActivation = false;
- }
-
- // Activate TSM
- if (!this->DoActivateTSM(true))
- {
- // Set the keyboard script to match my font's script, if necessary
- if (fMyFontScript != fPreviousFontScript)
- ::KeyScript(fMyFontScript);
- }
-
- // Call inherited
- FW_CEditView::ActivateTarget(ev, tabSelection);
- }
-
- //----------------------------------------------------------------------------------------
- // CJapEditView::DeactivateTarget
- //----------------------------------------------------------------------------------------
- void CJapEditView::DeactivateTarget(Environment* ev)
- {
- // Call inherited
- CMyEditView::DeactivateTarget(ev);
-
- // Deactivate TSM
- if (!this->DoActivateTSM(false))
- {
- // Restore the user's keyboard script
- ::KeyScript(fPreviousFontScript);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CJapEditView::DoMenu
- //----------------------------------------------------------------------------------------
- FW_Boolean CJapEditView::DoMenu(Environment* ev, const FW_CMenuEvent& theMenuEvent) // Override
- {
- FW_Boolean menuHandled = true;
- ODCommandID id = theMenuEvent.GetCommandID(ev);
-
- switch (id)
- {
- case kODCommandCut:
- case kODCommandCopy:
- case kODCommandPaste:
- case kODCommandClear:
- case kODCommandSelectAll: {
- menuHandled = CMyEditView::DoMenu(ev, theMenuEvent);
- this->DoFixTSMDocument();
- break;
- }
-
- default:
- menuHandled = FW_CEditView::DoMenu(ev, theMenuEvent);
- }
-
- return menuHandled;
- }
-
- //----------------------------------------------------------------------------------------
- void CJapEditView::InitJapEditView(Environment* ev)
- {
- // Create a TSM document, if TSMTE is present
- this->CreateTSMDocument((TEHandle)GetPlatformEditHandle(ev));
-
- // Save the font number
- fMyFont = gFontOsaka.MacGetFontID();
- // FW_ASSERT(fMyFontScript == ::FontToScript(fMyFont));
-
- // Set the font to Osaka - already done in constructor
- // FW_CEditView::SetFont(ev, gFontOsaka);
- }
-
- //-----------------------------------------------------------------------------------------
- void CJapEditView::AddInput(Environment* ev, CTSMInput* input)
- {
- FW_ASSERT(fTSMTypingCommand);
- fTSMTypingCommand->AddInput(ev, input);
- }
-
- //-----------------------------------------------------------------------------------------
- FW_Boolean CJapEditView::IsFirstEventInSequence()
- {
- if (fTSMTypingCommand == NULL) return true;
- return fTSMTypingCommand->IsCompleted();
- }
-
- //-----------------------------------------------------------------------------------------
- void CJapEditView::DoMakeTypingCommand(Environment* ev)
- {
- // If called by a callback routine, there's no SOM variable
- if (ev == NULL)
- ev = somGetGlobalEnvironment();
-
- this->DoneTyping(ev); // this was already called, presumably...
-
- fTSMTypingCommand = NewTypingCommand(ev, NULL); // no input yet
- fTypingCommand->Execute(ev, false); // calls DoIt, which calls SaveUndoState
- }
-
- //-----------------------------------------------------------------------------------------
- CTSMTypingCommand* CJapEditView::NewTypingCommand(Environment* ev, CTSMInput* firstInput)
- {
- CTSMTypingCommand* cmd = FW_NEW(CTSMTypingCommand, (ev, cTSMTypingCommand, GetFrame(ev),
- this, firstInput));
- fTypingCommand = cmd;
- return cmd;
- }
-
- //-----------------------------------------------------------------------------------------
- FW_Boolean CJapEditView::DoCharKey(Environment* ev, const FW_CCharKeyEvent& event)
- {
- // Ignore Command-characters which are not associated with menu commands
- if (event.GetModifiers() & cmdKey)
- return false;
-
- char ch = event.GetChar(ev);
-
- if (IsArrowKey(ch)) // arrow keys
- {
- this->DoneTyping(ev);
- }
- else if (ch == chBackspace)
- {
- if (this->IsFirstEventInSequence())
- {
- //--- Make a new typing command and save the Undo state
- this->DoMakeTypingCommand(ev);
- }
- fTSMTypingCommand->Backspace(ev);
- }
- else // user typed a single-byte character, such as a CR
- {
- //--- Make sure we have room for the character
- if (PrivCheckMaxChars(1))
- {
- FW_Beep();
- return true;
- }
-
- if (ch == chReturn) // CR
- {
- this->DoneTyping(ev);
- }
-
- //--- Pass character to the typing command
- CTSMInput input(ch);
- if (fTSMTypingCommand && fTSMTypingCommand->IsNotCompleted())
- fTSMTypingCommand->AddInput(ev, &input);
- else
- {
- fTSMTypingCommand = NewTypingCommand(ev, &input);
- fTSMTypingCommand->Execute(ev, false); // DoIt; don't delete if not undoable
- }
- }
-
- //--- Tell TextEdit to handle the character
- FW_CEditView::InputCharKey(ev, ch);
- return true;
- }
-
- //========================================================================================
- // CLASS CEditNotification
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // CEditNotification constructors
- //----------------------------------------------------------------------------------------
-
- CEditNotification::CEditNotification(FW_CEditView* editView) :
- FW_CNotification()
- {
- fEditView = editView;
- SetInterest(FW_CInterest((FW_MNotifier*)editView, kEditViewMsg));
- }
-
- //----------------------------------------------------------------------------------------
- CEditNotification::CEditNotification(const CEditNotification& other) :
- FW_CNotification(other),
- fEditView(other.fEditView)
- {
- }
-
- //----------------------------------------------------------------------------------------
- // CEditNotification destructor
- //----------------------------------------------------------------------------------------
-
- CEditNotification::~CEditNotification()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // CEditNotification::operator=
- //----------------------------------------------------------------------------------------
-
- CEditNotification& CEditNotification::operator= (const CEditNotification& other)
- {
- if (this != &other)
- {
- FW_CNotification::operator=(other);
- fEditView = other.fEditView;
- }
- return *this;
- }
-
- //========================================================================================
- // CMyEditView - for editing 1-byte scripts
- //========================================================================================
-
- FW_DEFINE_AUTO(CMyEditView)
-
- FW_DEFINE_CLASS_M1(CMyEditView, FW_CEditView);
-
- //----------------------------------------------------------------------------------------
- CMyEditView::CMyEditView(Environment* ev,
- FW_CSuperView* container,
- ODID viewId,
- const FW_CRect& bounds,
- const FW_CFont& font,
- short maxChars,
- unsigned short attributes)
- : FW_CEditView(ev, container, viewId, bounds, "", font, maxChars, attributes),
- fTypingCommand(NULL)
- {
- }
-
- //----------------------------------------------------------------------------------------
- CMyEditView::~CMyEditView()
- {
- }
-
- //-----------------------------------------------------------------------------------------
- FW_Boolean CMyEditView::DoCharKey(Environment* ev, const FW_CCharKeyEvent& event)
- {
- // Ignore Command-characters which are not associated with menu commands
- if (event.GetModifiers() & cmdKey)
- return false;
-
- char ch = event.GetChar(ev);
-
- if (IsArrowKey(ch)) // arrow keys
- {
- this->DoneTyping(ev);
- }
- else
- {
- if (ch != chBackspace)
- {
- //--- Make sure we have room for the character
- if (PrivCheckMaxChars(1))
- {
- FW_Beep();
- return true;
- }
-
- if (ch == FW_PlatformNewLineChar) // CR
- {
- this->DoneTyping(ev);
- }
- }
-
- //--- Pass character to the typing command
- if (fTypingCommand && fTypingCommand->IsNotCompleted())
- fTypingCommand->AddCharacter(ev, ch);
- else
- {
- fTypingCommand = NewTypingCommand(ev, ch);
- fTypingCommand->Execute(ev, false); // don't delete if not undoable
- }
- }
-
- //--- Tell TextEdit to handle the character
- FW_CEditView::InputCharKey(ev, ch);
- return true;
- }
-
- //-----------------------------------------------------------------------------------------
- FW_Boolean CMyEditView::DoMouseDown(Environment* ev, const FW_CMouseEvent& event)
- {
- this->DoneTyping(ev);
- return FW_CEditView::DoMouseDown(ev, event);
- }
-
- //-----------------------------------------------------------------------------------------
- void CMyEditView::DoneTyping(Environment* ev)
- {
- if (fTypingCommand)
- {
- fTypingCommand->CompleteTyping(ev);
- }
- }
-
- //-----------------------------------------------------------------------------------------
- FW_Boolean CMyEditView::IsArrowKey(char ch)
- {
- switch (ch)
- {
- case chLeft:
- case chRight:
- case chUp:
- case chDown:
- return true;
- }
- return false;
- }
-
- //-----------------------------------------------------------------------------------------
- CTypingCommand* CMyEditView::NewTypingCommand(Environment* ev, char firstChar)
- {
- CTypingCommand* cmd = FW_NEW(CTypingCommand, (ev, cTypingCommand, GetFrame(ev),
- this, true, firstChar));
- return cmd;
- }
-
- //----------------------------------------------------------------------------------------
- FW_Boolean CMyEditView::DoMenu(Environment* ev, const FW_CMenuEvent& theMenuEvent) // Override
- {
- FW_Boolean menuHandled = true;
- ODCommandID id = theMenuEvent.GetCommandID(ev);
-
- switch (id)
- {
- case kODCommandCut:
- case kODCommandCopy:
- case kODCommandPaste:
- case kODCommandClear:
- {
- this->DoneTyping(ev);
- // Create and execute one of our undoable clipboard commands
- FW_CClipboardCommand* cmd = GetFrame(ev)->NewClipboardCommand(ev, id);
- if (cmd)
- cmd->Execute(ev);
- break;
- }
-
- case kODCommandSelectAll:
- this->DoneTyping(ev);
- // fall thru to default case
-
- default:
- menuHandled = FW_CEditView::DoMenu(ev, theMenuEvent); // for Select All or whatever
- }
-
- return menuHandled;
- }
-
- //----------------------------------------------------------------------------------------
- void CMyEditView::DeactivateTarget(Environment* ev)
- {
- // finish the typing command
- this->DoneTyping(ev);
-
- // call inherited
- FW_CEditView::DeactivateTarget(ev);
- }
-
- //----------------------------------------------------------------------------------------
- void CMyEditView::LinkToReceiver(FW_MReceiver* receiver)
- {
- receiver->AddInterest(FW_CInterest(this, kEditViewMsg));
- }
-
-